package com.leejxx.backend.config;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.MessageDigestPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class MutiPasswordEncoder implements PasswordEncoder {


    private static final String PREFIX = "{";
    private static final String SUFFIX = "}";
    private static final Map<String, PasswordEncoder> encoders = new HashMap<>();

    public MutiPasswordEncoder() {
        encoders.put("bcrypt", new BCryptPasswordEncoder());
        encoders.put("MD5", new MessageDigestPasswordEncoder("MD5"));
        encoders.put("noop", org.springframework.security.crypto.password.NoOpPasswordEncoder.getInstance());
    }

    @Override
    public String encode(CharSequence rawPassword) {
        return null;
    }

    @Override
    public boolean matches(CharSequence rawPassword, String prefixEncodedPassword) {
        if (rawPassword == null && prefixEncodedPassword == null) {
            return true;
        }
        String id = extractId(prefixEncodedPassword);
        PasswordEncoder delegate = encoders.get(id);
        if (delegate == null) {
            // 处理MD5_<MD5值>的密码
            if (prefixEncodedPassword.contains("_")) {
                String newId = prefixEncodedPassword.substring(0, prefixEncodedPassword.indexOf("_"));
                PasswordEncoder newDelegate = encoders.get(newId);
                String encodedPassword = prefixEncodedPassword.substring(prefixEncodedPassword.indexOf("_") + 1);
                return newDelegate.matches(rawPassword, encodedPassword);
            }
            // 处理<加密值>的密码
            if (rawPassword.equals(prefixEncodedPassword)) {
                return true;
            }
            if (new MessageDigestPasswordEncoder("MD5").matches(rawPassword, prefixEncodedPassword)) {
                return true;
            }
            if (new BCryptPasswordEncoder().matches(rawPassword, prefixEncodedPassword)) {
                return true;
            }
            return false;
        }
        String encodedPassword = prefixEncodedPassword.substring(prefixEncodedPassword.indexOf(SUFFIX) + 1);
        return delegate.matches(rawPassword, encodedPassword);
    }

    private String extractId(String prefixEncodedPassword) {
        int start = prefixEncodedPassword.indexOf(PREFIX);
        if (start != 0) {
            return null;
        }
        int end = prefixEncodedPassword.indexOf(SUFFIX, start);
        if (end < 0) {
            return null;
        }
        return prefixEncodedPassword.substring(start + 1, end);
    }
}
